package com.tianyu.inspection.controller;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tianyu.inspection.common.Constants;
import com.tianyu.inspection.common.GeoUtils;
import com.tianyu.inspection.common.enums.RoState;
import com.tianyu.inspection.common.annotation.Permission;
import com.tianyu.inspection.common.component.Validate;
import com.tianyu.inspection.entity.Pipeline;
import com.tianyu.inspection.entity.PipelinePoint;
import com.tianyu.inspection.entity.model.OperateMo;
import com.tianyu.inspection.entity.model.QueryMo;
import com.tianyu.inspection.entity.vo.Point;
import com.tianyu.inspection.entity.vo.Ro;
import com.tianyu.inspection.entity.vo.ServiceRo;
import com.tianyu.inspection.service.api.IPipelineService;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**********************************
 * @Author YSW
 * @Description 管道相关接口
 * @Date 2021/1/15 - 17:21
 **********************************/

@RestController
@RequestMapping("/api/2.0/pipeline")
public class PipelineController {

    @Resource
    private IPipelineService pipelineService;

    @Resource
    private Validate validateModel;

    @GetMapping(value = "/list/oss/details")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<IPage<Pipeline>> getOssPipelineList(HttpServletRequest request, @RequestHeader("u-projectId") Integer projectId) {
        QueryMo queryMo = QueryMo.getQueryMo(request);
        Ro<IPage<Pipeline>> ro = new Ro<>();
        queryMo.build(Pipeline.class, projectId);
        return ro.setContent(pipelineService.getOssPipelineList(queryMo));
    }

    @GetMapping(value = "/list/details")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<IPage<Pipeline>> getDbPipelineList(HttpServletRequest request, @RequestHeader("u-projectId") Integer projectId) {
        QueryMo queryMo = QueryMo.getQueryMo(request);
        Ro<IPage<Pipeline>> ro = new Ro<>();
        queryMo.build(Pipeline.class, projectId);
        return ro.setContent(pipelineService.getDbPipelineList(queryMo));
    }

    @GetMapping(value = "/list")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Object> getPageList(HttpServletRequest request, @RequestHeader("u-projectId") Integer projectId) {
        QueryMo queryMo = QueryMo.getQueryMo(request);
        Ro<Object> ro = new Ro<>();
        queryMo.build(Pipeline.class, projectId);
        return ro.setContent(pipelineService.searchListPage(queryMo));
    }


    @GetMapping(value = "/list/tree")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Object> getLinesTree(HttpServletRequest request, @RequestHeader("u-projectId") Integer projectId) {
        QueryMo queryMo = QueryMo.getQueryMo(request);
        Ro<Object> ro = new Ro<>();
        queryMo.build(Pipeline.class, projectId);
        return ro.setContent(pipelineService.getLinesTree(queryMo));
    }


    @PostMapping(value = "/kml-json-load-prepare")
    @Permission(value = 2, tags = Constants.API_ADMIN)
    public Ro<Object> kmlJsonLoadPrepare(@RequestBody JSONObject kmlJSONObject) {
        Ro<Object> ro = new Ro<>();
        return ro.setContent(pipelineService.kmlJsonLoadPrepare(kmlJSONObject));
    }

    @PostMapping(value = "/kml-json-load")
    @Permission(value = 2, tags = Constants.API_ADMIN)
    public Ro<Object> kmlJsonLoad(@RequestBody JSONObject kmlJSONObject,
                                  @RequestHeader("u-projectId") Integer projectId,
                                  @RequestHeader("u-uid") Integer userId) {
        Ro<Object> ro = new Ro<>();
        return ro.setContent(pipelineService.kmlObjectLoad(kmlJSONObject, projectId, userId));
    }

    @GetMapping(value = "/list/tree/{id}")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Object> getLinesTree(HttpServletRequest request, @RequestHeader("u-projectId") Integer projectId, @PathVariable String id) {
        QueryMo queryMo = QueryMo.getQueryMo(request);
        queryMo.put("parentId", (Objects.equals(id, "-1") || "".equals(id)) ? null : id);
        Ro<Object> ro = new Ro<>();
        queryMo.build(Pipeline.class, projectId);
        return ro.setContent(pipelineService.getLinesTreeLevel(queryMo, id));
    }


    @PostMapping(value = "/electronicFence")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Object> electronicFence(@RequestBody QueryMo queryMo,
                                      @RequestHeader("u-projectId") Integer projectId) {
        Ro<Object> ro = new Ro<>(RoState.PARAMS_MISS_ERROR);
        Integer distance = (Integer) queryMo.get("distance");
        if (Objects.isNull(distance)) {
            return ro.setMessage("缺少参数[distance]");
        }
        if (distance == 0) {
            return ro.setMessage("电子围栏距离不能为0");
        }
        if (queryMo.get("points") != null) {
            try {
                JSONArray jsonArray = new ObjectMapper().convertValue(queryMo.get("points"), JSONArray.class);
                List<PipelinePoint> pointList = GeoUtils.queryBuffer(jsonArray, distance);
                return ro.setResultEnum(RoState.SUCCESS).setContent(pointList);
            } catch (Exception e) {
                return ro.setMessage("位置点解析失败");
            }
        }
        queryMo.put("type", 0);
        queryMo.build(Pipeline.class, projectId);
        final Object inMap1 = queryMo.get("inMap");
        if (inMap1 != null) {
            final ObjectMapper objectMapper = new ObjectMapper();
            Map<String, JSONArray> inMap = objectMapper.convertValue(queryMo.get("inMap"), new TypeReference<Map<String, JSONArray>>() {
            });
            queryMo.setInMap(inMap);
        }
        IPage<Pipeline> pipelineList = pipelineService.getDbPipelineList(queryMo);
        if (pipelineList.getRecords().size() == 0) {
            return ro.setState(RoState.FAIL.getValue()).setMessage("未查询到管线，不能生成电子围栏");
        } else {
            final JSONObject jsonObject = new JSONObject();
            List<Pipeline> pipelines = pipelineList.getRecords();
            pipelines.forEach(pipeline -> {
                Object points = pipeline.getPoints();
                JSONArray jsonArray = new ObjectMapper().convertValue(points, JSONArray.class);
                jsonObject.put(String.valueOf(pipeline.getId()), GeoUtils.queryBuffer(jsonArray, distance));
            });
            ro.setContent(jsonObject);
            return ro.setResultEnum(RoState.SUCCESS);
        }
    }


    @PostMapping(value = "/multi/electronicFence")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Object> multiElectronicFence(@RequestBody JSONArray queryItems,
                                           @RequestHeader("u-projectId") Integer projectId) {
//        for (Object item : queryItems) {
//            final QueryMo queryMo = JSONObject.from(item);
//            Ro<Object> ro = new Ro<>(RoState.PARAMS_MISS_ERROR);
//            Integer distance = (Integer) queryMo.get("distance");
//            if (Objects.isNull(distance)) {
//                return ro.setMessage("缺少参数[distance]");
//            }
//            if (distance == 0) {
//                return ro.setMessage("电子围栏距离不能为0");
//            }
//            if (queryMo.get("points") != null) {
//                try {
//                    JSONArray jsonArray = new ObjectMapper().convertValue(queryMo.get("points"), JSONArray.class);
//                    List<PipelinePoint> pointList = GeoUtils.queryBuffer(jsonArray, distance);
//                    return ro.setResultEnum(RoState.SUCCESS).setContent(pointList);
//                } catch (Exception e) {
//                    return ro.setMessage("位置点解析失败");
//                }
//            }
//            queryMo.build(Pipeline.class, projectId);
//            IPage<Pipeline> pipelineList = pipelineService.getDbPipelineList(queryMo);
//            if (pipelineList.getRecords().size() == 0) {
//                return ro.setState(RoState.FAIL.getValue()).setMessage("未查询到管线，不能生成电子围栏");
//            } else {
//                List<Pipeline> pipelines = pipelineList.getRecords();
//                pipelines.forEach(pipeline -> {
//                    Object points = pipeline.getPoints();
//                    JSONArray jsonArray = new ObjectMapper().convertValue(points, JSONArray.class);
//                    pipeline.setPoints(GeoUtils.queryBuffer(jsonArray, distance));
//                    pipeline.setState(null).setProjectId(null).setPointsUrl(null).setPointsCount(null).setCenterPoint(null);
//                });
//                ro.setContent(pipelines);
//                return ro.setResultEnum(RoState.SUCCESS);
//            }
//        }
        return null;
    }

    @GetMapping(value = "/{id}")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Pipeline> getOne(@PathVariable Integer id,
                               @RequestHeader("u-projectId") Integer projectId) {
        Ro<Pipeline> ro = new Ro<>();
        if (Objects.isNull(id)) {
            return ro.setResultEnum(RoState.PARAMS_MISS_ERROR);
        }
        QueryMo queryMo = new QueryMo();
        queryMo.put("id", id);
        queryMo.build(Pipeline.class, projectId);
        Pipeline pipeline = pipelineService.selectOne(queryMo);
        if (Objects.isNull(pipeline)) {
            ro.setMessage("未查询到数据");
        } else {
            ro.setContent(pipeline);
        }
        return ro;
    }

    @GetMapping(value = "/details/{id}")
    @Permission(value = 4, tags = Constants.API_PATROL)
    public Ro<Pipeline> getOneDetails(@PathVariable Integer id, @RequestHeader("u-projectId") Integer projectId) {
        Ro<Pipeline> ro = new Ro<>();
        if (Objects.isNull(id)) {
            return ro.setResultEnum(RoState.PARAMS_MISS_ERROR);
        }
        QueryMo queryMo = new QueryMo();
        queryMo.put("id", id);
        queryMo.build(Pipeline.class, projectId);
        Pipeline pipeline = pipelineService.selectOneDetails(queryMo);
        if (Objects.isNull(pipeline)) {
            ro.setMessage("未查询到数据");
        } else {
            ro.setContent(pipeline);
        }
        return ro;
    }

    @PostMapping(value = "/admin/upload")
    @Permission(value = 1, tags = Constants.API_SUPER)
    public Ro<List<Point>> uploadFilePipeline(@RequestParam("file") MultipartFile pipelineFile,
                                              @RequestParam("pipelineName") String pipelineName,
                                              @RequestParam("projectId") Integer projectId) {
        Ro<List<Point>> ro = new Ro<>();
        if (Objects.isNull(pipelineFile)) {
            return ro.setResultEnum(RoState.FAIL).setMessage("参数错误[pipelineFile]");
        }
        if (Objects.isNull(pipelineName)) {
            return ro.setResultEnum(RoState.FAIL).setMessage("参数错误[pipelineName]");
        }
        if (Objects.isNull(projectId)) {
            return ro.setResultEnum(RoState.FAIL).setMessage("参数错误[projectId]");
        } else {
            if (validateModel.projectIdValidate(projectId)) {
                return ro.setResultEnum(RoState.FAIL).setMessage("参数错误[projectId]");
            }
        }
        if (!pipelineService.ossPipelineSave(pipelineFile, pipelineName, projectId)) {
            ro.setResultEnum(RoState.FAIL);
        }
        return ro;
    }

    @PostMapping(value = "/admin/upload2")
    @Permission(value = 1, tags = Constants.API_SUPER)
    public Ro<List<Point>> uploadObjPipeline(@RequestBody JSONObject jsonObj) {
        Ro<List<Point>> ro = new Ro<>();
        if (Objects.isNull(jsonObj)) {
            return ro.setResultEnum(RoState.FAIL).setMessage("参数错误");
        } else {
            final Boolean isMultiple = jsonObj.getBoolean("isMultiple");
            final Object pipelineData = jsonObj.get("pipelineData");
            final Integer projectId = jsonObj.getInteger("projectId");
            if (Objects.isNull(isMultiple) || Objects.isNull(pipelineData) || Objects.isNull(projectId)) {
                return ro.setResultEnum(RoState.FAIL).setMessage("参数错误");
            } else {
                if (validateModel.projectIdValidate(projectId)) {
                    return ro.setResultEnum(RoState.FAIL).setMessage("项目ID错误");
                }
            }
        }
        if (!pipelineService.ossPipelineSaveByJson(jsonObj)) {
            return ro.setResultEnum(RoState.FAIL);
        }
        return ro;
    }

    @PostMapping(value = "/admin/load")
    @Permission(value = 1, tags = Constants.API_SUPER)
    public Ro<List<PipelinePoint>> loadPipeline(@RequestParam("file") MultipartFile pipelineFile) {
        Ro<List<PipelinePoint>> ro = new Ro<>();
        if (pipelineFile.isEmpty()) {
            return ro.setResultEnum(RoState.FAIL).setMessage("参数[file]为null");
        }
        List<PipelinePoint> pipelinePoints = pipelineService.loadPipeline(pipelineFile);
        if (Objects.isNull(pipelinePoints)) {
            return ro.setResultEnum(RoState.FAIL).setMessage("文件解析错误");
        }
        return ro.setContent(pipelinePoints);
    }

    @PatchMapping(value = "/modify")
    @Permission(value = 2, tags = Constants.API_ADMIN)
    public Ro<Pipeline> modify(@RequestBody OperateMo operateMo, @RequestHeader("u-projectId") Integer projectId) {
        Ro<Pipeline> ro = new Ro<>();
        final ServiceRo serviceRo = operateMo.updateBuild(Pipeline.class, projectId);
        if (!serviceRo.getResult()) {
            return ro.setResultEnum(RoState.FAIL).setMessage(serviceRo.getMessage());
        }
        if (operateMo.getEntity().size() == 0) {
            return ro.setResultEnum(RoState.FAIL).setMessage("无操作参数传入,请传参后重试");
        }
        if (Objects.isNull(operateMo.get("id"))) {
            return ro.setResultEnum(RoState.FAIL).setMessage("缺少[id]字段,请传参后重试");
        }
        if (!pipelineService.update(operateMo)) {
            ro.setResultEnum(RoState.FAIL).setMessage("参数无匹配,修改失败");
        }
        return ro;
    }

    @DeleteMapping(value = "/delete/{id}")
    @Permission(value = 2, tags = Constants.API_ADMIN)
    public Ro<Pipeline> delete(@PathVariable Integer id, @RequestHeader("u-projectId") Integer projectId) {
        Ro<Pipeline> ro = new Ro<>();
        QueryMo queryMo = new QueryMo();
        queryMo.put("id", id);
        queryMo.build(Pipeline.class, projectId);
        ModelMap resultMap = pipelineService.deleteOne(queryMo);
        boolean isDbHasRecord = (boolean) resultMap.get("isDbHasRecord");
        boolean isDbPipelineDelete = (boolean) resultMap.get("isDbPipelineDelete");
        if (!isDbHasRecord) {
            return ro.setResultEnum(RoState.FAIL).setMessage("无匹配ID,删除失败");
        }
        if (!isDbPipelineDelete) {
            return ro.setResultEnum(RoState.FAIL);
        }
        return ro;
    }

    @DeleteMapping(value = "/admin/delete/logical/{id}")
    @Permission(value = 1, tags = Constants.API_SUPER)
    public Ro<Pipeline> logicallyDelete(@PathVariable Integer id, @RequestHeader("u-projectId") Integer projectId) {
        Ro<Pipeline> ro = new Ro<>();
        QueryMo queryMo = new QueryMo();
        queryMo.put("id", id);
        queryMo.build(Pipeline.class, projectId);
        if (!pipelineService.logicallyDelete(queryMo)) {
            ro.setResultEnum(RoState.FAIL).setMessage("无匹配ID,删除失败");
        }
        return ro;
    }
}
